package com.xuecheng.content.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.xuecheng.api.content.model.dto.CourseBaseDTO;
import com.xuecheng.api.content.model.qo.QueryCourseModel;
import com.xuecheng.common.domain.code.CommonErrorCode;
import com.xuecheng.common.domain.page.PageRequestParams;
import com.xuecheng.common.domain.page.PageVO;
import com.xuecheng.common.enums.common.CommonEnum;
import com.xuecheng.common.enums.content.CourseAuditEnum;
import com.xuecheng.common.enums.content.CourseChargeEnum;
import com.xuecheng.common.exception.ExceptionCast;
import com.xuecheng.common.util.StringUtil;
import com.xuecheng.content.common.constant.ContentErrorCode;
import com.xuecheng.content.convert.CourseBaseConvert;
import com.xuecheng.content.entity.CourseBase;
import com.xuecheng.content.entity.CourseMarket;
import com.xuecheng.content.mapper.CourseBaseMapper;
import com.xuecheng.content.service.CourseBaseService;
import com.xuecheng.content.service.CourseMarketService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 课程基本信息 服务实现类
 * </p>
 *
 * @author itcast
 */
@Slf4j
@Service
public class CourseBaseServiceImpl extends ServiceImpl<CourseBaseMapper, CourseBase> implements CourseBaseService {


    @Autowired
    private CourseMarketService courseMarketService;

    /**
     * <p>
     * 根据课程id查询课程基本信息
     * </p>
     *
     * @param courseBaseId 课程id
     * @return CourseBaseDTO
     */
    @Override
    public CourseBaseDTO getCourseBaseById(Long courseBaseId, Long companyId) {
        //判断数据合法性
        if (ObjectUtils.isEmpty(courseBaseId) || ObjectUtils.isEmpty(companyId)) {
            throw new RuntimeException("数据不合法");
        }

        CourseBase courseBaseById = this.getById(courseBaseId);
        //判断要查询的课程是否存在
        if (ObjectUtils.isEmpty(courseBaseById)) {
            throw new RuntimeException("无此课程");
        }

        //判断修改的课程所属机构和数据库里的机构是否一致
        if (!ObjectUtils.nullSafeEquals(companyId, courseBaseById.getCompanyId())) {
            throw new RuntimeException("无权访问");
        }

        CourseBaseDTO courseBaseDTO = CourseBaseConvert.INSTANCE.courseBaseToDto(courseBaseById);
        //查询营销信息
        CourseMarket courseMarket = courseMarketService.getOne(Wrappers.lambdaQuery(CourseMarket.class).eq(CourseMarket::getCourseId, courseBaseDTO.getCourseBaseId()));
        courseBaseDTO.setCharge(courseMarket.getCharge());
        if (!ObjectUtils.isEmpty(courseMarket.getPrice())) {
            courseBaseDTO.setPrice(new BigDecimal(courseMarket.getPrice().toString()));
        }
        return courseBaseDTO;
    }

    /**
     * @param params    分页参数
     * @param model     查询条件
     * @param companyId 学成公司id
     * @return PageVO
     * @description 课程基本信息分页及条件查询
     */
    @Override
    public PageVO<CourseBaseDTO> queryCourseList(PageRequestParams params, QueryCourseModel model, Long companyId) {
        // 1.业务传入参数的判断
        if (ObjectUtils.isEmpty(params)) {
            params = new PageRequestParams();
        }
        Long pageNo = params.getPageNo();
        Integer pageSize = params.getPageSize();
        // 2.构建分页查询
        if (ObjectUtils.isEmpty(pageNo) || pageNo < 1) {
            pageNo = PageRequestParams.DEFAULT_PAGE_NUM;
        }
        if (ObjectUtils.isEmpty(pageSize) || pageSize < 1) {
            pageSize = PageRequestParams.DEFAULT_PAGE_SIZE;
        }
        Page<CourseBase> page = new Page<>(pageNo, pageSize);
        // 3.构建条件查询
        LambdaQueryWrapper<CourseBase> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StringUtil.isNotBlank(model.getAuditStatus()), CourseBase::getAuditStatus, model.getAuditStatus());
        queryWrapper.like(StringUtil.isNotBlank(model.getCourseName()), CourseBase::getName, model.getCourseName());
        //此处实现数据隔离，根据公司id只查询这个id下的内容
        // 增加功能 companyId为空时，认为时运营人员查询所有课程
        queryWrapper.eq(!ObjectUtils.isEmpty(companyId), CourseBase::getCompanyId, companyId);
        queryWrapper.eq(CourseBase::getStatus, CommonEnum.USING_FLAG.getCode());
        // 4.查询
        Page<CourseBase> pageResult = this.page(page, queryWrapper);
        List<CourseBase> records = pageResult.getRecords();
        // 5.封装PageVo
        List<CourseBaseDTO> courseBaseDTOS = Collections.emptyList();
        if (!ObjectUtils.isEmpty(records)) {
            //使用mapStruct转换对象
            courseBaseDTOS = CourseBaseConvert.INSTANCE.courseBaseToDtoList(records);
        }
        return new PageVO<>(courseBaseDTOS, page.getTotal(), pageNo, pageSize);
    }

    /**
     * 新增课程基本信息
     *
     * @param courseBaseDTO {@link CourseBaseDTO}
     * @return boolean 操作的结果
     */
    @Transactional
    @Override
    public CourseBaseDTO createCourseBase(CourseBaseDTO courseBaseDTO) {

        verifyCourseBaseInfo(courseBaseDTO);

        CourseBase courseBase = CourseBaseConvert.INSTANCE.dtoToCourseBase(courseBaseDTO);
        //设置审核状态为未提交
        courseBase.setAuditStatus(CourseAuditEnum.AUDIT_UNPAST_STATUS.getCode());

        boolean save = this.save(courseBase);
        if (!save) {
            ExceptionCast.cast(ContentErrorCode.E_120001);
        }
        //保存对应的课程营销对象
        CourseMarket courseMarket = new CourseMarket();
        courseMarket.setCourseId(courseBase.getId());
        //课程价格为空判断
        courseMarket.setPrice(ObjectUtils.isEmpty(courseBaseDTO.getPrice()) ? 0 : courseBaseDTO.getPrice().floatValue());
        courseMarket.setCharge(courseBaseDTO.getCharge());

        boolean flag = courseMarketService.save(courseMarket);
        if (!flag) {
            ExceptionCast.cast(ContentErrorCode.E_120110);
        }
        CourseBase byId = this.getById(courseBase.getId());
        CourseBaseDTO resultDto = CourseBaseConvert.INSTANCE.courseBaseToDto(byId);
        resultDto.setCharge(courseMarket.getCharge());
        resultDto.setPrice(new BigDecimal(courseMarket.getPrice().toString()));
        return resultDto;
    }

    private void verifyCourseBaseInfo(CourseBaseDTO courseBaseDTO) {
        if (ObjectUtils.isEmpty(courseBaseDTO)) {
            ExceptionCast.cast(CommonErrorCode.E_100116);
        }
        //1.1 判断课程名称
        if (StringUtils.isEmpty(courseBaseDTO.getName()))
            ExceptionCast.cast(ContentErrorCode.E_120004);
        //1.2 判断课程大分类
        if (StringUtils.isEmpty(courseBaseDTO.getMt()))
            ExceptionCast.cast(ContentErrorCode.E_120002);
        //1.3 判断课程小分类
        if (StringUtils.isEmpty(courseBaseDTO.getSt()))
            ExceptionCast.cast(ContentErrorCode.E_120003);
        //1.4 判断课程等级
        if (StringUtils.isEmpty(courseBaseDTO.getGrade()))
            ExceptionCast.cast(ContentErrorCode.E_120007);
        //1.5 判断课程教学模式
        if (StringUtils.isEmpty(courseBaseDTO.getTeachmode()))
            ExceptionCast.cast(ContentErrorCode.E_120006);
        //1.6 判断课程收费规则
        if (StringUtils.isEmpty(courseBaseDTO.getCharge())) {
            ExceptionCast.cast(ContentErrorCode.E_120104);
        }
    }

    /**
     * <p>
     * 修改课程信息
     * </p>
     *
     * @param courseBaseDTO courseBaseDTO对象
     * @return CourseBaseDTO
     */
    @Transactional
    @Override
    public CourseBaseDTO modifyCourseBase(CourseBaseDTO courseBaseDTO) {
        //判断传入的DTO数据合法性
        this.verifyCourseBaseInfo(courseBaseDTO);
        //判断课程id是否有效
        CourseBase courseBase = getById(courseBaseDTO.getCourseBaseId());
        if (ObjectUtils.isEmpty(courseBase)) {
            ExceptionCast.cast(ContentErrorCode.E_120013);
        }
        //判断机构是否合法
        if (!ObjectUtils.nullSafeEquals(courseBaseDTO.getCompanyId(), courseBase.getCompanyId())) {
            ExceptionCast.cast(CommonErrorCode.E_100108);
        }
        //判断审核状态
        String auditStatus = courseBase.getAuditStatus();
        if (!StringUtils.equals(auditStatus, CourseAuditEnum.AUDIT_UNPAST_STATUS.getCode())
                && !StringUtils.equals(auditStatus, CourseAuditEnum.AUDIT_DISPAST_STATUS.getCode())) {
            ExceptionCast.cast(ContentErrorCode.E_120011);
        }
        CourseBase updateCourse = CourseBaseConvert.INSTANCE.dtoToCourseBase(courseBaseDTO);
        LambdaUpdateWrapper<CourseBase> updateWrapper = Wrappers.lambdaUpdate(CourseBase.class).eq(CourseBase::getId, courseBase.getId());

        boolean result = this.update(updateCourse, updateWrapper);
        if (!result) {
            ExceptionCast.cast(ContentErrorCode.E_120001);
        }


        LambdaUpdateWrapper<CourseMarket> marketLambdaUpdateWrapper = Wrappers.lambdaUpdate(CourseMarket.class).eq(CourseMarket::getCourseId, courseBase.getId())
                .set(CourseMarket::getCharge, courseBaseDTO.getCharge());
        String charge = courseBaseDTO.getCharge();

        if (!StringUtils.equals(charge, CourseChargeEnum.CHARGE_NO.getCode()) &&
                !StringUtils.equals(charge, CourseChargeEnum.CHARGE_YES.getCode())) {
            throw new RuntimeException("课程收费规则非法");
        }
        float price = 0f;
        if (StringUtils.equals(charge, CourseChargeEnum.CHARGE_YES.getCode())) {
            price = courseBaseDTO.getPrice() == null ? 0 : courseBaseDTO.getPrice().floatValue();
        } else if (courseBaseDTO.getPrice().floatValue() != 0) {
            throw new RuntimeException("免费课程无法设置价格");
        }
        marketLambdaUpdateWrapper.set(CourseMarket::getPrice, price);
        courseMarketService.update(marketLambdaUpdateWrapper);
        courseBaseDTO.setChangeDate(updateCourse.getChangeDate());
        courseBaseDTO.setPrice(new BigDecimal(String.valueOf(price)));
        return courseBaseDTO;
    }


    /**
     * <p>
     * 根据课程id删除课程
     * </p>
     *
     * @param courseBaseId 要删除的课程id
     * @param companyId    机构id
     * @return boolean
     */
    @Override
    @Transactional
    public boolean deleteCourseBaseById(Long courseBaseId, Long companyId) {
        //校验传入参数的合法性
        if (ObjectUtils.isEmpty(companyId) || ObjectUtils.isEmpty(courseBaseId)) {
            throw new RuntimeException("数据不合法");
        }
        //查看操作的机构是否合法
        CourseBase courseBase = getById(courseBaseId);
        if (!ObjectUtils.nullSafeEquals(courseBase.getCompanyId(), companyId)) {
            throw new RuntimeException("不是所属机构课程，操作不合法");
        }
        if (courseBase.getStatus() == 0) {
            throw new RuntimeException("操作非法");
        }
        // 判断课程的审核状态 已提交，审核通过，已发布的不能删除
        String auditStatus = courseBase.getAuditStatus();
        if (StringUtils.equals(auditStatus, CourseAuditEnum.AUDIT_PASTED_STATUS.getCode())
                || StringUtils.equals(auditStatus, CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode())
                || StringUtils.equals(auditStatus, CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode())) {
            throw new RuntimeException("操作非法,课程已发布或已审核");
        }
        LambdaUpdateWrapper<CourseBase> updateWrapper = Wrappers.lambdaUpdate(courseBase)
                .eq(CourseBase::getId, courseBaseId)
                .set(CourseBase::getStatus, 0);
        boolean update = update(updateWrapper);
        if (!update) {
            throw new RuntimeException("删除操作失败！");
        }
        return true;
    }

    /**
     * <p>
     * 课程信息提交审核
     * </p>
     *
     * @param courseBaseId 课程id
     * @param companyId    机构id
     */
    @Override
    @Transactional
    public void commitCourseBase(Long courseBaseId, Long companyId) {
        //判断是否传入课程id
        CourseBase courseBase = verifyCourseInfo(courseBaseId, companyId);
        String auditStatus = courseBase.getAuditStatus();
        if (StringUtils.equals(auditStatus, CourseAuditEnum.AUDIT_PASTED_STATUS.getCode())
                || StringUtils.equals(auditStatus, CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode())
                || StringUtils.equals(auditStatus, CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode())) {
            ExceptionCast.cast(ContentErrorCode.E_120014);
        }
        courseBase.setAuditStatus(CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode());
        boolean update = this.updateById(courseBase);
        if (!update) {
            ExceptionCast.cast(ContentErrorCode.E_120017);
        }

    }

    /**
     * <p>
     * 审核课程信息
     * </p>
     *
     * @param params 传入的审核数据
     * @return void
     */
    @Override
    public void approveCourseBase(Map<String, Object> params) {
        Long courseBaseId = Long.valueOf((params.get("courseBaseId").toString()));
        String auditStatus = String.valueOf(params.get("auditStatus"));
        String auditMind = String.valueOf(params.get("auditMind"));
        //判断是否传入课程id
        if (ObjectUtils.isEmpty(courseBaseId)) {
            ExceptionCast.cast(ContentErrorCode.E_120009);
        }
        //判断课程信息是否存在
        CourseBase courseBase = this.getById(courseBaseId);
        if (ObjectUtils.isEmpty(courseBase)) {
            ExceptionCast.cast(ContentErrorCode.E_120013);
        }
        if (!StringUtils.equals(courseBase.getAuditStatus(), CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode())) {
            ExceptionCast.cast(ContentErrorCode.E_120015);
        }
        if (!StringUtils.equals(auditStatus, CourseAuditEnum.AUDIT_DISPAST_STATUS.getCode()) &&
                !StringUtils.equals(auditStatus, CourseAuditEnum.AUDIT_PASTED_STATUS.getCode())) {
            ExceptionCast.cast(ContentErrorCode.E_120016);
        }
        courseBase.setAuditStatus(auditStatus);
        courseBase.setAuditMind(auditMind);
        courseBase.setAuditDate(LocalDateTime.now());
        Integer nums = courseBase.getAuditNums();
        courseBase.setAuditNums(nums == null ? 1 : nums + 1);
        boolean update = this.updateById(courseBase);
        if (!update) {
            ExceptionCast.cast(ContentErrorCode.E_120001);
        }
    }

    private CourseBase verifyCourseInfo(Long courseId, Long companyId) {
        //判断是否传入课程id
        if (ObjectUtils.isEmpty(courseId)) {
            ExceptionCast.cast(ContentErrorCode.E_120009);
        }
        //判断课程信息是否存在
        CourseBase courseBase = this.getById(courseId);
        if (ObjectUtils.isEmpty(courseBase)) {
            ExceptionCast.cast(ContentErrorCode.E_120013);
        }
        //判断操作机构是否正确
        if (!ObjectUtils.nullSafeEquals(companyId, courseBase.getCompanyId())) {
            ExceptionCast.cast(CommonErrorCode.E_100108);
        }
        return courseBase;
    }


}
